using System;
using System.Collections.Generic;
using System.Text;

namespace zeroflag.Windows.Custom
{
	public interface ISelectable
	{
		bool Selected { get; set; }
	}

	public class SelectedItems<ParentType, ValueType> : IList<ValueType>
		where ValueType : class
	{
		public SelectedItems()
		{
			if (typeof(ValueType).IsSubclassOf(typeof(ISelectable)))
			{
				this.SetSelect = delegate(ValueType item, bool selected)
				{
					((ISelectable)item).Selected = selected;
				};
				this.GetSelect = delegate(ValueType item)
				{
					return ((ISelectable)item).Selected;
				};
			}
		}

		#region Parent
		ParentType m_Parent;

		public ParentType Parent
		{
			get { return m_Parent; }
			set { m_Parent = value; }
		}
		#endregion Parent

		#region Set/Get Select
		public delegate void SetSelectHandler(ValueType item, bool selected);
		public delegate bool GetSelectHandler(ValueType item);

		SetSelectHandler m_SetSelect;

		public SetSelectHandler SetSelect
		{
			get { return m_SetSelect; }
			set { m_SetSelect = value; }
		}

		GetSelectHandler m_GetSelect;

		public GetSelectHandler GetSelect
		{
			get { return m_GetSelect; }
			set { m_GetSelect = value; }
		}
		#endregion Set/Get Select

		#region Items
		List<ValueType> m_Items = new List<ValueType>();

		protected virtual List<ValueType> Items
		{
			get { return m_Items; }
			set { m_Items = value; }
		}
		#endregion Items


		#region ItemChanged event
		public delegate void ItemChangedHandler(object sender, ValueType oldvalue, ValueType newvalue);

		private event ItemChangedHandler m_ItemChanged;
		/// <summary>
		/// Occurs when an Item changes.
		/// </summary>
		public event ItemChangedHandler ItemChanged
		{
			add { this.m_ItemChanged += value; }
			remove { this.m_ItemChanged -= value; }
		}

		/// <summary>
		/// Raises the ItemChanged event.
		/// </summary>
		protected virtual void OnItemChanged(ValueType oldvalue, ValueType newvalue)
		{
			// if there are event subscribers...
			if (this.m_ItemChanged != null)
			{
				// call them...
				this.m_ItemChanged(this, oldvalue, newvalue);
			}
		}
		#endregion ItemChanged event

		#region IList<ValueType> Members

		public int IndexOf(ValueType item)
		{
			return this.Items.IndexOf(item);
		}

		public void Insert(int index, ValueType item)
		{
			if (item != null)
			{
				this.OnItemChanged(null, item);
			}

			this.Items.Insert(index, item);
		}

		public void RemoveAt(int index)
		{
			if (index >= 0 && index < this.Count)
			{
				this.OnItemChanged(this[index], null);
			}
			this.Items.RemoveAt(index);
		}

		public ValueType this[int index]
		{
			get
			{
				return this.Items[index];
			}
			set
			{
				if (this.Items[index] != value)
				{
					this.OnItemChanged(this.Items[index], this.Items[index] = value);
				}
			}
		}

		#endregion

		#region ICollection<ValueType> Members

		public void Add(ValueType item)
		{
			if (item != null)
			{
				this.OnItemChanged(null, item);
			}
			this.Items.Add(item);
		}

		public void Clear()
		{
			while (this.Count > 0)
			{
				this.RemoveAt(0);
			}
		}

		public bool Contains(ValueType item)
		{
			return this.Items.Contains(item);
		}

		public void CopyTo(ValueType[] array, int arrayIndex)
		{
			this.Items.CopyTo(array, arrayIndex);
		}

		public int Count
		{
			get { return this.Items.Count; }
		}

		public bool IsReadOnly
		{
			get { return false; }
		}

		public bool Remove(ValueType item)
		{
			if (item != null)
			{
				this.OnItemChanged(item, null);
			}
			return this.Items.Remove(item);
		}

		#endregion

		#region IEnumerable<ValueType> Members

		public IEnumerator<ValueType> GetEnumerator()
		{
			return this.Items.GetEnumerator();
		}

		#endregion

		#region IEnumerable Members

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return this.Items.GetEnumerator();
		}

		#endregion
	}
}
